home *** CD-ROM | disk | FTP | other *** search
- /*
- PrintfExit.c
-
- PrintfExit(const char *format,...);
- is normally equivalent to calling printf and exit.
-
- Lots of VideoToolbox routines, when they find a really grievous error, print out
- a message and exit. Having one routine that does both makes the code slightly
- neater, since the if statement then doesn't need braces. Furthermore, both of
- these functions, printf, and exit are liable to break in foreign environments,
- e.g. when running as a MEX resource under MATLAB. Now the problem is confined to
- this file, where it can be handled by conditional compilation.
-
- Since PrintfExit is called only when we're near death, it seems prudent to make
- sure there's enough stack space before calling printf, which crashes if there's
- less than about 4500 byts of stack. Note that StackGrow() moves memory.
-
- I've replaced all calls to exit() in the entire VideoToolbox by calls to
- PrintfExit().
-
- StackGrow() is defined in VideoToolbox.h.
-
- 3/4/97 dhb & dgp. There's a bunch of new code here to deal with the translation
- of \n to \r and \r to \n. This is necessary when we use THINK C to compile
- a MEX file, because THINK C and MATLAB use incompatible codes for newline and return.
- To work, this uses #defines in VideoToolbox.h, something like the following:
-
- #if MATLAB && THINK_C
- #undef printf
- #undef mexPrintf
- #undef mexWarnMsgTxt
- #undef mexErrorMsgTxt
- #define printf Printf
- #define mexPrintf Printf
- #define mexWarnMsgTxt(s) mexWarnMsgTxt(TranslateEOL(s))
- #define mexErrorMsgTxt(s) mexErrorMsgTxt(TranslateEOL(s))
- #end
-
- With other compilers (e.g. Metrowerks CodeWarrior) the standard #defines in mex.h are fine,
- provided you set the compiler option "MPW newlines".
-
- HISTORY:
- 2/20/93 dgp Wrote it based on conversation with David Brainard.
- 7/9/93 dgp Test MATLAB in #if instead of #ifdef.
- 9/12/93 dgp Moved Required() to Require.c.
- 9/15/93 dgp Added "const" to prototype.
- 6/7/95 dhb, gmb SIOUX stuff conditional on not MATLAB
- 9/27/95 dgp SIOUX stuff conditional on MAC_C
- 8/30/95 dhb updated for MATLAB 4 and 5.
- 1/18/97 dgp increased MATLAB temporary string buffer from 256 to 1024 bytes.
- 3/4/97 dhb increased it again to 4096 bytes.
- dhb added TranslateEOL routine.
- 3/5/97 dgp It's dangerous to assume we can get 4 KB from the stack, so we
- instead allocate a scratch area with NewPtr.
- 3/15/97 dgp psychTable->restoreScreensAtError.
- 3/17/97 dhb The inclusion of psych table means we need PsychLibSources.h too. Added.
- 3/17/97 dgp Call GetPsychTable only once, to avoid infinite loop.
- 3/28/97 dgp Use psychTable->restoreScreensA4 to restore A4 for that routine.
- 3/31/97 dgp Use psychTable->restoringScreensAtError.
- 4/15/97 dgp SetPriority(0) if MATLAB.
- 4/17/97 dgp Don't bother to SetPriority(0) if we already know that it's zero.
- 4/21/97 dgp Deleted the obsolete commented-out restoreScreensAtError code.
- */
- #include "VideoToolbox.h"
- #include <stdarg.h> /* for variable-number-of-argument macros */
- #if MATLAB
- #include "PsychLibSources.h"
- #endif
-
- static char *GetScratch(long bytes);
- static void DisposeScratch();
-
- int PrintfExit(const char *format,...)
- {
- va_list args;
- int i;
- long qD=0;
-
- #if MAC_C
- #if __MWERKS__ && !MATLAB
- SIOUXSettings.autocloseonquit=0;
- #endif
- /*
- The main program may have changed the current device. Let's
- restore the main device before doing the printf. Most Standard C libraries
- on the Mac crash if you call printf and the current device is not the main
- device. I've suggested to both Symantec and Metrowerks that their stdout console code
- could easily take the precaution of ensuring that the MainDevice is the current device
- (to set & restore, if necessary, or at least not crash),
- but, last I checked, they took no heed.
- */
- Gestalt(gestaltQuickdrawVersion,&qD);
- if(qD>=gestalt8BitQD)SetGDevice(GetMainDevice());
- //if(StackSpace()<6000)StackGrow(6000-StackSpace());
- #endif
- #if !MATLAB
- #if MAC_C
- /* printf crashes if there's less than about 4500 bytes of stack space */
- if(StackSpace()<5000){
- SysBeep(20);
- exit(EXIT_FAILURE);
- }
- #endif
- va_start(args,format);
- i=vfprintf(stdout,format,args);
- va_end(args);
- #if __MWERKS__
- printf("Hit Command-Q to quit.\n");
- #endif
- exit(EXIT_FAILURE);
- #else
- {
- char *s=GetScratch(4000);
-
- va_start(args,format);
- i=vsprintf(s,format,args);
- va_end(args);
- #undef mexPrintf
- if(strlen(s)+1>4000)mexPrintf("%s buffer overrun.\n\r",__FILE__);
- {
- PsychTable *psychTable=GetPsychTable();// defined in <PsychLibSources.h>
- Boolean screensActive=0;
-
- if(psychTable!=NULL){
- if(psychTable->priority!=0){
- SetPriority(0);
- psychTable->priority=0;
- }
- }else SetPriority(0);
- ShowCursor();
- s[2000-200-1]=0;
- if(psychTable!=NULL){
- if(!psychTable->restoringScreensAtError && !psychTable->restoringScreensAtFlush){
- screensActive=psychTable->windowTableHead!=NULL;
- for(i=0;i<MAX_SCREENS;i++)screensActive |= psychTable->screenInfo[i].valid;
- // mexEvalString() always returns, even if an error occurred.
- if(screensActive){
- psychTable->restoringScreensAtError=1;
- strcpy(s+2000,s);
- mexEvalString("SCREEN('CloseAll')"); // Restore screens.
- strcpy(s,s+2000);
- psychTable->restoringScreensAtError=0;
- }
- }
- if(psychTable->restoringScreensAtError){
- memmove(s+200,s,strlen(s)+1);
- sprintf(s,"Double trouble! An error occurred while restoring screens to "
- "report another error.\n%s",s+200);
- psychTable->restoringScreensAtError=0;
- }
- if(psychTable->restoringScreensAtFlush){
- memmove(s+200,s,strlen(s)+1);
- sprintf(s,"An error occurred while restoring screens before MATLAB flushes SCREEN.mex.\n%s",s+200);
- psychTable->restoringScreensAtFlush=0;
- }
- }else{
- static Boolean restoringScreensAtError=0;
- if(!restoringScreensAtError){
- restoringScreensAtError=1;
- // if we knew we were in SCREEN.mex we could skip the call to mexEvalString.
- // mexEvalString() always returns, even if an error occurred.
- strcpy(s+2000,s);
- mexEvalString("SCREEN('CloseAll')"); // Restore screens.
- strcpy(s,s+2000);
- }else{
- memmove(s+200,s,strlen(s)+1);
- sprintf(s,"Double trouble! An error occurred while restoring screens to "
- "report another error.\n%s",s+200);
- }
- restoringScreensAtError=0;
- }
- }
- #undef mexErrMsgTxt
- mexErrMsgTxt(TranslateEOL(s)); /* Ask MATLAB to report the error. */
- }
- #endif
- return 0; /* Can't get here */
- }
-
- #if MATLAB
- // Printf is used solely by calls to printf that are redefined as Printf so
- // as to benefit from TranslateEOL processing.
- // #define printf Printf
-
- int Printf(const char *format,...)
- {
- va_list args;
- int i;
- long qD=0;
-
- Gestalt(gestaltQuickdrawVersion,&qD);
- if(qD>=gestalt8BitQD)SetGDevice(GetMainDevice());
- {
- char *s=GetScratch(4000);
-
- va_start(args,format);
- i=vsprintf(s,format,args);
- va_end(args);
- #undef mexPrintf
- if(strlen(s)+1>4000)mexPrintf("%s buffer overrun.\n\r",__FILE__);
- mexPrintf("%s",TranslateEOL(s));
- }
- return i;
- }
- #endif
-
- /*
- ROUTINE: TranslateEOL
- PURPOSE:
- Turn \n into \r conditional on THINK and MATLAB. This
- deals with the incompatible newline conventions in MATLAB vs THINK C.
-
- Note the special case of being called by Printf or PrintfExit. The string
- will be our scratch area. The string fits in the scratch area so sOut==string.
- The translation will thus be done in place, which is ok.
- */
-
- char *TranslateEOL(char *string) {
- #if THINK_C
- int i;
- char *sOut;
- static Boolean firstTime = 1;
- static char map[256];
-
- if (firstTime) {
- firstTime = 0;
- AtExitToShell(&DisposeScratch);
- for(i=0;i<256;i++)map[i]=i;
- map['\n']='\r';
- map['\r']='\n';
- }
-
- // Translate into the scratch area.
- sOut=GetScratch(strlen(string)+1);
- for(i=0;string[i]!=0;i++)sOut[i]=map[string[i]];
-
- // Return the translated string. Valid until the scratch area is reused.
- return(sOut);
- #else
- return string;
- #endif
- }
-
- static char *trScratch = NULL; // PRIVATE!! used only by GetScratch & DisposeScratch
-
- static char *GetScratch(long bytes)
- {
- // Allocate scratch space if not yet allocated or too small.
- if(trScratch!=NULL && GetPtrSize(trScratch)<bytes){
- DisposePtr(trScratch);
- trScratch=NULL;
- }
- if(trScratch==NULL)trScratch=NewPtr(bytes);
- if(trScratch==NULL) {
- char s[128];
-
- sprintf(s,"%s: can't allocate %ld bytes.\n\r",__FILE__,bytes);
- #if !MATLAB
- #undef printf
- printf("%s",s);
- exit(EXIT_FAILURE);
- #else
- mexErrMsgTxt(s);
- #endif
- }
- return trScratch;
- }
-
- static void DisposeScratch()
- {
- if(trScratch!=NULL){
- DisposePtr(trScratch);
- trScratch=NULL;
- }
- }
-